package wci.frontend.pascal;

import static wci.message.MessageType.PARSER_SUMMARY;

import java.util.EnumSet;

import wci.frontend.EofToken;
import wci.frontend.Parser;
import wci.frontend.Scanner;
import wci.frontend.Token;
import wci.frontend.pascal.parsers.ProgramParser;
import wci.intermediate.symtabimpl.Predefined;
import wci.message.Message;

/**
 * <h1>PascalParserTD</h1>
 * 
 * <p>
 * Top-Down模式的Pascal Parser，Pascal解析器的基类
 * </p>
 * <p>
 * Copyright (c) 2009 by Ronald Mak<br>
 * For instructional purposes only. No warranties.
 * </p>
 */
public class PascalParserTD extends Parser {

	protected PascalErrorHandler errorHandler = new PascalErrorHandler();
	
	public PascalParserTD(Scanner scanner) {
		super(scanner);
	}

	/* 新增链条解析(Parser Chain) */
	public PascalParserTD(PascalParserTD parent) {
		super(parent.getScanner());
	}
	//有了ProgramParser，这个没有意义了
	//private SymTabEntry routineId; 
	/*public SymTabEntry getRoutineId() {
		return routineId;
	}
	public void setRoutineId(SymTabEntry routineId) {
		this.routineId = routineId;
	}*/
	/**
	 * Pascal的解析过程，交由ProgramParser
	 */
	public void parse() throws Exception {

		long startTime = System.currentTimeMillis();
		//ICode iCode = ICodeFactory.createICode();
		//初始化预定义
		Predefined.initialize(symTabStack);
		try {
            Token token = nextToken();

            // 解析程序
            ProgramParser programParser = new ProgramParser(this);
            programParser.parse(token, null);
            token = currentToken();

            // 发送编译摘要消息
            float elapsedTime = (System.currentTimeMillis() - startTime)/1000f;
            sendMessage(new Message(PARSER_SUMMARY,
                                    new Number[] {token.getLineNumber(),
                                                  getErrorCount(),
                                                  elapsedTime}));
        }
        catch (java.io.IOException ex) {
            errorHandler.abortTranslation(PascalErrorCode.IO_ERROR, this);
        }
	}

	public int getErrorCount() {
		return errorHandler.getErrorCount();
	}
	/**
	 * 同步解析器的当前token到集合所允许的Token
	 * @param syncSet 下一步有效的token集合
	 * @return 找到的某个有效的token
	 * @throws Exception
	 */
	public Token synchronize(EnumSet syncSet) throws Exception {
		Token token = currentToken();
		//如果当前token不在同步集合里，那么就需要跳跃到结合范围内的token。
		if (!syncSet.contains(token.getType())) {
			//报告一个解析错误然后继续往前解析
			errorHandler.flag(token, PascalErrorCode.UNEXPECTED_TOKEN, this);
			do {
				token = nextToken();
			} while (!(token instanceof EofToken)
					&& !syncSet.contains(token.getType()));
		}
		return token;
	}
}
